# -*- coding: utf-8 -*-
# Trabalho de Inteligência Artificial
# Semestre 2009.2
# Mineração de Dados
# O classificador em si

import sys, os

# Biblioteca de mineração de dados que implementa o KNN, Bayes e Majority
import orange

# Biblioteca que implementa o ID3
import id3

# Biblioteca que implementa um classificador simples
import simple

# Aqui definimos o dataset a ser usado, a ser passado como parâmetro
if len(sys.argv) == 1:
	print "Forneça como parâmetro o nome do dataset! Deve ser um dos seguintes:"
	os.system("ls | grep tab | sed 's/-.*$//g' | uniq")
	sys.exit(0)
else:
	dataset = sys.argv[1]

train_set = dataset + "-train"
test_set = dataset + "-test"
train_data = orange.ExampleTable(train_set)
test_data = orange.ExampleTable(test_set)

# Número de classes e atributos deste domínio

print "************************************************************"
print "* Trabalho de Inteligência Artificial - Mineração de Dados *"
print "************************************************************"
print "Utilizando o dataset", dataset
print "Classes:", len(train_data.domain.classVar.values) 
print "Classes possíveis:", train_data.domain.classVar.values 
print "Atributos possíveis:", train_data.domain
print "Atributos:", len(train_data.domain.attributes), ",", 

# Quantos são discretos ou contínuos 

ncont = 0
ndisc = 0
for a in train_data.domain.attributes: 
	if a.varType == orange.VarTypes.Discrete: 
		ndisc = ndisc + 1 
	else: 
		ncont = ncont + 1 
print ncont, "contínuos,", ndisc, "discretos" 

# Como essas classes se distribuem

c = [0] * len(train_data.domain.classVar.values) 
for e in train_data: 
	c[int(e.getclass())] += 1 
print "Instâncias: ", len(train_data), "total",
for i in range(len(train_data.domain.classVar.values)): 
	print ",", c[i], "da classe", train_data.domain.classVar.values[i], 
print

# Uma vez com os dados carregados, vamos treinar os algoritmos
# Classificando com os que o Orange já implementa

bayes = orange.BayesLearner(train_data)
knn = orange.kNNLearner(train_data, k=21) 
id3 = id3.Learner(train_data)
simple = simple.Learner(train_data)

bayes.name = "Naive Bayes"
knn.name = "KNN"
id3.name = "ID3"
simple.name = "Simple"

classifiers = [bayes, knn, id3, simple] 

# Imprime o cabeçalho
x = 0
if len(sys.argv) >= 3:
	if not sys.argv[2] in train_data.domain.classVar.values:
		print 'Classe inválida! Deveria ser uma das seguintes: %s' % (train_data.domain.classVar.values)
		sys.exit(0)
	x = train_data.domain.classVar.values.index(sys.argv[2])

print '---------------------------------------------------------------------------------'
print "Probabilidade para %s/classificação:" % (train_data.domain.classVar.values[x]) 
print '---------------------------------------------------------------------------------'
print "Classe Original",
for l in classifiers:
	print "%-22s " % (l.name),
print

# Aqui vamos contabilizar os acertos de cada algoritmo para depois medir suas acurácias
correct = dict()
for c in classifiers:
	correct[c.name] = 0

# Iterando pelos dados de teste
n = len(test_data)
for example in test_data:
	print "%-14s " % (example.getclass()),
	for c in classifiers: 
		v, p = apply(c, [example, orange.GetBoth]) 
		print "%.3f/%-16s " % (p[x], v),
		if apply(c, [example]) == example.getclass(): 
			correct[c.name] += 1
	print
print '---------------------------------------------------------------------------------'
print

# Mostrando a acurácia de cada um
print '---------------------------------------------------------------------------------'
print "Acurácia:"
print '---------------------------------------------------------------------------------'
for k,v in correct.items():
	print "%-13s | Acertos: %d/%d    Acurácia: %.3f" % (k, v, n, float(v)/float(n))
print '---------------------------------------------------------------------------------'
